package com.mmall.service.impl;

import com.mmall.common.Const;
import com.mmall.common.ServerResponse;
import com.mmall.common.TokenCache;
import com.mmall.dao.UserMapper;
import com.mmall.pojo.User;
import com.mmall.service.IUserService;
import com.mmall.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * Created by Administrator on 2017/12/6.
 */
@Service("iUserService")
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Override
    /***
     * 用户登录的实现方法
     */
    public ServerResponse<User> login(String username, String password) {
        int resultCount=userMapper.checkUsername(username); //检查用户名是否存在 根据返回值不同进行
        if (resultCount==0){
            return  ServerResponse.createByErrorMessage("用户名不存在");
        }
        // TODO: 2017/12/6  密码登录MD5加密
        String Md5Password = MD5Util.MD5EncodeUtf8(password); //调用工具类来实现密码的加密
        User user= userMapper.selectLogin(username,Md5Password);
        if(user==null){
            return  ServerResponse.createByErrorMessage("密码错误");
        }//检验成功后需要将传递给前端的密码设置为空
        user.setPassword(StringUtils.EMPTY);

        return ServerResponse.createBySuccess("登录成功",user); //将对象返回给前端
    }
    /***
     * 用户注册的实现方法
     * 1.首先校验用户名是否存在
     * 2.校验邮箱是否存在
     * 3.默认用户角色为用户需要在常量类中使用内部接口类定义 有点不想枚举那么繁重 达到区分的效果
     * 4.实现用户输入密码的MD5加密 数据库中存储的密码都是加密以后的
     * @param user
     * @return
     */
    public  ServerResponse<String> register(User user){
        // 校验用户名是否存在
        ServerResponse validResponse =this.checkValid(user.getUsername(),Const.USERNAME);
        if(!validResponse.isSuccess()){
            return validResponse;
        }
        //校验email是否存在
        validResponse=this.checkValid(user.getEmail(),Const.EMAIL);
        if(!validResponse.isSuccess()){
            return  validResponse;
        }
        //默认注册的角色为用户
        user.setRole(Const.Role.ROLE_CUSTOMER);
        //密码的MD5加密
        user.setPassword(MD5Util.MD5EncodeUtf8(user.getPassword()));
       int  resultCount=userMapper.insert(user);
        if(resultCount==0){
            return  ServerResponse.createByErrorMessage("注册失败");
        }else {
            return  ServerResponse.createBySuccess("注册成功");
        }


    }

    /***
     * 校验用户名和email是否存在
     * 重点关注的是type的值是什么 username或者是email
     * 通过调用isNotBlank（type）来判断是否type存在  需要注意idNotBlank 与IsEmpty的区别
     * 如果存在判断是否为Username or email 然后通过UserMapping接口--->UserMapper.xml 相应的方法进行数据查询
     * @param str
     * @param type
     * @return
     */
    public  ServerResponse<String> checkValid(String str,String type){
            if (StringUtils.isNotBlank(type)){
                //开始校验
                if(Const.USERNAME.equals(type)){
                    int resultCount=userMapper.checkUsername(str); //检查用户名是否存在 根据返回值不同进行
                    if (resultCount>0){
                        return  ServerResponse.createByErrorMessage("用户名已存在");
                    }
                }
                if (Const.EMAIL.equals(type)){
                    int resultCount=userMapper.checkEmail(str);
                    if (resultCount>0){
                        return  ServerResponse.createByErrorMessage("email已存在");
                    }
                }
            }else{
                return  ServerResponse.createByErrorMessage("参数错误");
            }
                return  ServerResponse.createBySuccessMessage("校验成功");
    }

    /***
     * 1.首先根据传入的用户名判断 用户名是否存在 调用checkValid（string str ,string type）方法
     *
     * @param username
     * @return
     */
    public ServerResponse selectQuestion(String username){
        ServerResponse validResponse=this.checkValid(username,Const.USERNAME);
        if (validResponse.isSuccess()){
            //用户名不存在
            return  ServerResponse.createByErrorMessage("用户名不存在");
        }
        String question=userMapper.selectQuestionByUsername(username);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(question)){
            return  ServerResponse.createBySuccess(question);
        }
        return  ServerResponse.createByErrorMessage("找回密码的问题是空的");

    }

    /***
     * 提示问题和答案
     * 首先根据传递的参数去数据库中查询 如果查询到数据 判断返回值resultCount是否>1
     * 大于说明这个问题与密码是当前用户的 然后将通过UUID整理好的username放入到缓存中设置缓存的有效时间 采用LRU算法  最小使用算法
     * 同时将缓存返回
     * ResultCount <=0如果错误直接返回错误信息
     * @param username
     * @param question
     * @param answer
     * @return
     */
    public  ServerResponse<String> checkAnswer(String username, String question,String answer){
            int resultCount=userMapper.checkAnswer(username,question,answer);
            if (resultCount>0){
                //说明问题以及答案是这个用户的
                String forgetToken= UUID.randomUUID().toString();
                //需要将forgetToken放置到本地缓存中并设置有效期

                TokenCache.setKey(TokenCache.TOKEN_PREFIX+username,forgetToken);//设置缓存中的key 和value

                String token = TokenCache.getKey(TokenCache.TOKEN_PREFIX+username);
                System.out.println(token);
                if(org.apache.commons.lang3.StringUtils.isBlank(token)){
                    return ServerResponse.createByErrorMessage("token无效或者过期");
                }

                return  ServerResponse.createBySuccess(forgetToken);
            }
            return  ServerResponse.createByErrorMessage("问题的答案错误");
    }

    /***
     * 首先根据userId 和passwordOld 避免横向越权校验是否旧密码是否错误 注意传递的密码采用了MD5加密
     * 如果正确 修改（通过MD5加密的）新密码
     * 调用updateByPrimaryKeySelective（User user） 方法实现更新操作 注意这个方法只更新变动的字段 类似于ajax
     * 对更细结果进行判断
     * token有效执行密码更新操作 需要传递参数username passwordNew
     * @param passwordOld
     * @param passwordNew
     * @param user
     * @return
     */
    public  ServerResponse<String> resetPassword(String passwordOld,String passwordNew,User user){
        //防止横向越权，要校验用户就旧的密码就一定要校验这个用户的id  如果  因为我们会查询count(1)，如果不指定那么结果就是truecount>0;
        int resultCount=userMapper.checkPassword(MD5Util.MD5EncodeUtf8(passwordOld),user.getId());
        if(resultCount==0){
            return ServerResponse.createByErrorMessage("旧密码错误");
        }
        user.setPassword(MD5Util.MD5EncodeUtf8(passwordNew)); //将新的密码加密
        int updateCount =userMapper.updateByPrimaryKeySelective(user);
        if (updateCount>0){
            return  ServerResponse.createBySuccessMessage("密码更新成功");
        }
        return  ServerResponse.createByErrorMessage("密码更新失败");
    }

    /***
     * 首先校验一下token的正确性
     * 然后校验username的是否存在
     * 然后校验token是否过期
     * @param username
     * @param passwordNew
     * @param forgetToken
     * @return
     */
    public ServerResponse<String> forgetResetPassword(String username,String passwordNew,String forgetToken){
        System.out.println("passwordNew"+passwordNew);
        if(org.apache.commons.lang3.StringUtils.isBlank(forgetToken)){
            return ServerResponse.createByErrorMessage("参数错误,token需要传递");
        }
        ServerResponse validResponse = this.checkValid(username,Const.USERNAME);
        if(validResponse.isSuccess()){
            //用户不存在
            return ServerResponse.createByErrorMessage("用户不存在");
        }

        String token = TokenCache.getKey(TokenCache.TOKEN_PREFIX+username);

        if(org.apache.commons.lang3.StringUtils.isBlank(token)){
            return ServerResponse.createByErrorMessage("token无效或者过期");
        }

        if(org.apache.commons.lang3.StringUtils.equals(forgetToken,token)){
            System.out.println("passwordNew"+passwordNew);
            System.out.println("Md5passwordNew"+ MD5Util.MD5EncodeUtf8(passwordNew));
            String md5Password = MD5Util.MD5EncodeUtf8(passwordNew);
            int rowCount = userMapper.updatePasswordByUsername(username,md5Password);

            if(rowCount > 0){
                return ServerResponse.createBySuccessMessage("修改密码成功");
            }
        }else{
            return ServerResponse.createByErrorMessage("token错误,请重新获取重置密码的token");
        }
        return ServerResponse.createByErrorMessage("修改密码失败");
    }

    public  ServerResponse<User> updateInformation(User user){
        //userId是不能被更新的
        // email 也要进行校验 校验email是否已经存在 如果存在 不能是我们当前用户的 当前用户不能更新
        int resultCount=userMapper.checkEmailByUserId(user.getEmail(),user.getId());
        if (resultCount>0){
            return  ServerResponse.createByErrorMessage("email 已经存在 请更换email尝试更新");
        }
        User updateuser=new User();//获取前端用户输入的信息
        updateuser.setId(user.getId());
        updateuser.setEmail(user.getEmail());
        updateuser.setPhone(user.getPhone());
        updateuser.setQuestion(user.getQuestion());
        updateuser.setAnswer(user.getAnswer());
        int updateCount=userMapper.updateByPrimaryKeySelective(updateuser);//更新信息
        if(updateCount>0){
            return  ServerResponse.createBySuccess("更新个人信息成功！",updateuser);
        }
        return  ServerResponse.createByErrorMessage("更新个人信息失败");


    }

    public  ServerResponse<User> getInformation(Integer userId){
        User user=userMapper.selectByPrimaryKey(userId);
        if(user==null){
            return  ServerResponse.createByErrorMessage("找不到当前用户");
        }
        user.setPassword(StringUtils.EMPTY); //将密码制空不返回给前台
         return  ServerResponse.createBySuccess(user);
    }

  /*  public static void main(String[] args) {
        System.out.println(UUID.randomUUID().toString());
    }*/

   /* public static void main(String[] args) {
        UserServiceImpl one=new UserServiceImpl();
        System.out.println( one.selectQuestion("one"));

    }*/

}
